﻿/*-------------------------------------------------------------------------
 * 版权所有：	黑客马拉松
 * 作者：		罗毅
 * 联系方式：	whluoyi@gmail.com
 * 创建时间：	2016/10/29 11:23:16
 * 版本号：		v1.0
 * 用途描述：	日志代理
 *  -------------------------------------------------------------------------*/

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml;


namespace SuperMarieApi.Log.LogAgent.Xml
{
    /// <summary>
    /// Xml读取解析
    /// </summary>
    /// <typeparam name="T"></typeparam>
    internal class XRead
    {
        #region 解析 Read
        #region 获取节点
        /// <summary>
        /// 判断是否是需要读取的节点
        /// </summary>
        /// <param name="node"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        private bool isReaderNode(string node, string reader)
        {
            if (node == null || reader == null)
            {
                if (node == null && reader == null)
                {
                    return true;
                }
                return false;
            }
            node = node.Trim();
            reader = reader.Trim();
            if (node == "*" || reader == "*")
            {
                return true;
            }
            return node.Equals(reader, StringComparison.CurrentCultureIgnoreCase);
        }
        /// <summary>
        /// 判断是否是需要读取的节点
        /// </summary>
        /// <param name="node"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        private bool isReaderNode(XmlNode node, XReader reader)
        {
            if (node is XmlCDataSection || node is XmlText)
            {
                return false;
            }
            string nodeName = reader.NodeName.Trim();
            if (nodeName.Contains("\\"))
            {
                string[] names = nodeName.Split('\\');
                XmlNode thisNode = node;
                bool result = true;
                for (int i = names.Length; i > 0; i--)
                {
                    string thisName = names[i - 1];
                    result = (isReaderNode(thisNode.Name, thisName));
                    if (!result)
                    {
                        return result;
                    }
                    thisNode = thisNode.ParentNode;
                }
                return result;
            }
            else
            {
                return (isReaderNode(node.Name, nodeName));
            }
        }
        /// <summary>
        /// 获取顶层需要读取的节点
        /// </summary>
        /// <param name="node"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        private List<XmlNode> getReaderNode(XmlNode node, XReader reader)
        {
            var result = new List<XmlNode>();
            if (isReaderNode(node, reader))
            {
                result.Add(node);
            }
            if (result.Count > 0)
            {
                return result;
            }
            if (node.HasChildNodes)
            {
                foreach (XmlNode cnode in node.ChildNodes)
                {
                    result.AddRange(getReaderNode(cnode, reader));
                }
            }
            return result;
        }
        #endregion
        #region 获取属性
        /// <summary>
        /// 是否是文本节点
        /// </summary>
        /// <param name="xmlNode"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private bool isXmlCharacterData(XmlNode xmlNode, ref string value)
        {
            if (xmlNode!=null && xmlNode.HasChildNodes && xmlNode.FirstChild is XmlCharacterData)
            {
                value = (xmlNode.FirstChild as XmlCharacterData).Data;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 是否是add节点
        /// </summary>
        /// <param name="xmlNode"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private bool isAddKeyValue(XmlNode xmlNode, ref string key, ref string value)
        {
            if (!xmlNode.Name.Equals("add", StringComparison.CurrentCultureIgnoreCase))
            {
                return false;
            }
            var hasKey = false;
            var hasValue = false;
            var nodeKey = string.Empty;
            var nodeValue = string.Empty;
            foreach (XmlAttribute attribute in xmlNode.Attributes)
            {
                if (attribute.Name.Equals("key", StringComparison.CurrentCultureIgnoreCase))
                {
                    hasKey = true;
                    nodeKey = attribute.Value;
                }
                if (attribute.Name.Equals("value", StringComparison.CurrentCultureIgnoreCase))
                {
                    hasValue = true;
                    nodeValue = attribute.Value;
                }
            }
            if (!hasValue)
            {
                hasValue = isXmlCharacterData(xmlNode,ref nodeValue);
            }
            if (hasKey && hasValue)
            {
                key = nodeKey;
                value = nodeValue;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 整理生成XRow
        /// </summary>
        /// <param name="xmlNode"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        private XRow createXRow(XmlNode xmlNode, XReader reader)
        {
            var xRow = new XRow(reader);
            xRow.Name = xmlNode.Name;
            xRow.Node = xmlNode;
            foreach (XmlAttribute attribute in xmlNode.Attributes)
            {
                var dataKey = attribute.Name;
                var dataValue = attribute.Value;
                xRow.KeyValue.Add(dataKey, dataValue);
            }
            var key = string.Empty;
            var value = string.Empty;
            if (isXmlCharacterData(xmlNode, ref value))
            {
                xRow.KeyValue.Add(XRow.XML_CDATA_NAME, value);
            }
            foreach (XmlNode cNode in xmlNode.ChildNodes)
            {
                if (isAddKeyValue(cNode,ref key, ref value))
                {
                    xRow.KeyValue.Add(key, value);
                    continue;
                }
                if (cNode.ChildNodes.Count == 1
                    && (isXmlCharacterData(cNode, ref value)))
                {
                    xRow.KeyValue.Add(cNode.Name, value);
                    continue;
                }
            }
            return xRow;
        }
        #endregion
        /// <summary>
        /// 读取XRow
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public XRow[] Read(XReader reader)
        {
            var nodes = getReaderNode(reader.Node, reader);
            var xRows = new List<XRow>();
            foreach (XmlNode node in nodes)
            {
                xRows.Add(createXRow(node, reader));
            }
            return xRows.ToArray();
        }
        #endregion

        #region 数据树 XNode
        /// <summary>
        /// 创建数据树节点
        /// </summary>
        /// <param name="xRow"></param>
        /// <param name="root"></param>
        /// <returns></returns>
        private XNode creatXRowNode(XRow xRow, ref XNode root)
        {
            XNode result = new XNode();
            result.Parent = root;
            result.XRow = xRow;
            root.Children.Add(result);
            return result;
        }
        /// <summary>
        /// 读取数据树
        /// </summary>
        /// <param name="parNode"></param>
        /// <returns></returns>
        private void readxRowTree(XReader reader, ref XNode root)
        {
            var xRows = Read(reader);
            foreach (var xRow in xRows)
            {
                XNode node = creatXRowNode(xRow, ref root);
                foreach (XmlNode cnode in xRow.Node.ChildNodes)
                {
                    var nodeReader = new XReader(cnode);
                    readxRowTree(nodeReader, ref node);
                }
            }
        }
        /// <summary>
        /// 读取数据树
        /// </summary>
        /// <param name="parNode"></param>
        /// <returns></returns>
        public XNode ReadTree(XReader reader)
        {
            XNode root = new XNode();
            readxRowTree(reader, ref root);
            if (root.Children.Count == 1 && root.Parent == null)
            {
                root = root.Children[0];
                root.Parent = null;
            }
            return root;
        }
        #endregion

    }

}
